package com.snowfeel.sfmall.promotion.config;

import com.snowfeel.sfmall.promotion.context.CouponContext;
import com.snowfeel.sfmall.promotion.enums.CouponActivityStatusEnum;
import com.snowfeel.sfmall.promotion.event.CouponStatusChangeEvent;
import com.snowfeel.small.statemachine.Action;
import com.snowfeel.small.statemachine.Condition;
import com.snowfeel.small.statemachine.StateMachine;
import com.snowfeel.small.statemachine.builder.StateMachineBuilder;
import com.snowfeel.small.statemachine.builder.factory.StateMachineBuilderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Date;
import java.util.Objects;

/**
 * @author guomenghuai
 * @date 2024/9/5
 * @Description
 */
@Configuration
public class CouponStateMachineConfig {

    private static final Logger logger = LoggerFactory.getLogger(CouponStateMachineConfig.class);

    final String MACHINE_ID = "CouponStateMachine";

    @Bean("couponStateMachine")
    public StateMachine<CouponActivityStatusEnum, CouponStatusChangeEvent, CouponContext> stateMachine() {
        //创建 一个StateMachineBuilder 实例，用于构建和配置状态机
        StateMachineBuilder<CouponActivityStatusEnum, CouponStatusChangeEvent, CouponContext> builder = StateMachineBuilderFactory.create();

        // 1-待发放，2-未开始，3-进行中，4-已结束，5-已暂停
        //因为没有源状态，初始化时只是同一个状态流转;所以用内部流转
        builder.internalTransition()
                .within(CouponActivityStatusEnum.WAIT_GRANT)
                .on(CouponStatusChangeEvent.CREATED)
                .perform(doAction());

        // 待发放->未开始
        builder.externalTransition()
                .from(CouponActivityStatusEnum.WAIT_GRANT)
                .to(CouponActivityStatusEnum.UN_START)
                .on(CouponStatusChangeEvent.PUBLISH)
                .when(checkIfUnStarted())
                .perform(doAction());

        // 待发放->进行中
        builder.externalTransition()
                .from(CouponActivityStatusEnum.WAIT_GRANT)
                .to(CouponActivityStatusEnum.IN_PROGRESS)
                .on(CouponStatusChangeEvent.PUBLISH)
                .when(checkIfStarted())
                .perform(doAction());

        // 已暂停->未开始
        builder.externalTransition()
                .from(CouponActivityStatusEnum.PAUSED)
                .to(CouponActivityStatusEnum.UN_START)
                .on(CouponStatusChangeEvent.PUBLISH)
                .when(checkIfUnStarted())
                .perform(doAction());

        // 已暂停->进行中
        builder.externalTransition()
                .from(CouponActivityStatusEnum.PAUSED)
                .to(CouponActivityStatusEnum.IN_PROGRESS)
                .on(CouponStatusChangeEvent.PUBLISH)
                .when(checkIfStarted())
                .perform(doAction());

        // 进行中->已暂停
        builder.externalTransition()
                .from(CouponActivityStatusEnum.IN_PROGRESS)
                .to(CouponActivityStatusEnum.PAUSED)
                .on(CouponStatusChangeEvent.PAUSED)
                .when(checkIfPaused())
                .perform(doAction());

        return builder.build(MACHINE_ID);
    }

    private Condition<CouponContext> checkIfUnStarted() {
        return (ctx) -> {
            // 大于发布开始时间，小于发布结束时间
            if (new Date().before(ctx.getGrantStartTime())) {
                return true;
            } else {
                return false;
            }
        };
    }

    private Condition<CouponContext> checkIfStarted() {
        return (ctx) -> {
            // 大于发布开始时间，小于发布结束时间
            if (new Date().after(ctx.getGrantStartTime()) && new Date().before(ctx.getGrantEndTime())) {
                return true;
            } else {
                return false;
            }
        };
    }

    private Condition<CouponContext> checkIfPaused() {
        return (ctx) -> {
            // 状态为暂停
            if (Objects.equals(CouponActivityStatusEnum.PAUSED.getCode(), ctx.getStatus())) {
                return true;
            } else {
                return false;
            }
        };
    }

    private Action<CouponActivityStatusEnum, CouponStatusChangeEvent, CouponContext> doAction() {
        return (from, to, event, ctx) -> {
            System.out.println("from:" + from + " to:" + to + " on:" + event + " condition:" + ctx);
        };
    }
}
